package com.mingqijia.gassafety.webserver.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mingqijia.gassafety.authority.api.resp.config.DictionaryItemRespDTO;
import com.mingqijia.gassafety.authority.dal.helper.ConfigureHolder;
import com.mingqijia.gassafety.db.entity.Consumer;
import com.mingqijia.gassafety.db.entity.Dtu;
import com.mingqijia.gassafety.db.entity.DtuBindingOrder;
import com.mingqijia.gassafety.db.influxdb.config.InfluxDBConfiguration;
import com.mingqijia.gassafety.db.influxdb.config.InfluxDBConnect;
import com.mingqijia.gassafety.db.mapper.DeviceStateMapper;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.constant.EquipmentType;
import com.mingqijia.gassafety.shared.constant.PageColumnConst;
import com.mingqijia.gassafety.shared.constant.TemplateTypeEnum;
import com.mingqijia.gassafety.shared.dto.UserFuncCodePermissionDTO;
import com.mingqijia.gassafety.shared.utils.ApplicationUtils;
import com.mingqijia.gassafety.shared.utils.HeaderUtil;
import com.mingqijia.gassafety.shared.utils.commonUtils.PageColumns;
import com.mingqijia.gassafety.shared.utils.commonUtils.PageUtil;
import com.mingqijia.gassafety.webserver.request.LatestLogListRequest;
import com.mingqijia.gassafety.webserver.request.PowerLogRequest;
import com.mingqijia.gassafety.webserver.response.CompanyResponse;
import com.mingqijia.gassafety.webserver.response.PowerLogResponse;
import com.mingqijia.gassafety.webserver.response.sk.AlarmSupplierListVo;
import com.mingqijia.gassafety.webserver.response.sk.ConsoleSkSupplierListResponse;
import com.mingqijia.gassafety.webserver.service.*;
import com.mingqijia.gassafety.webserver.service.cmp.EquipmentCmpService;
import com.mingqijia.gassafety.webserver.service.workorder.DtuBindingOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.StringUtil;
import org.influxdb.dto.QueryResult;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.mingqijia.gassafety.shared.constant.Constants.ORG_MAP_SUBSCODE;

/**
 * <p>
 * 开关机记录 服务实现类
 * </p>
 *
 * @author guoliang.lao
 * @since 2022-03-04
 */
@Service
@Slf4j
public class PowerLogServiceImpl implements PowerLogService {

    @Autowired
    EquipmentService equipmentService;
    @Autowired
    DeviceStateMapper deviceStateMapper;
    @Autowired
    InfluxDBConfiguration influxDBConfiguration;
    @Autowired
    ConsumerService consumerService;
    @Autowired
    ConfigureHolder holder;
    @Autowired
    DepartmentService departmentService;
    @Autowired
    DtuBindingOrderService dtuBindingOrderService;
    @Autowired
    HeaderUtil headerUtil;
    @Autowired
    CompanyService companyService;

    @Autowired
    UserPermissionService userPermissionService;

    @Autowired
    EquipmentCmpService equipmentCmpService;


    @Override
    public PageUtil<PowerLogResponse> list(PowerLogRequest req) {
        List<PowerLogResponse> resultList = new ArrayList<>();
        req.setTemplateType(headerUtil.getTemplateType());
        //页面字段模板
        List<PageColumns> pageColumns = new ArrayList<>();
        if (TemplateTypeEnum.TEMPLATE_TYPE_1.getCode() == req.getTemplateType()) {
            pageColumns = PageColumnConst.add(PageColumnConst.PowerGasUserTitles, PageColumnConst.PowerGasUserIndices);
        } else if (TemplateTypeEnum.TEMPLATE_TYPE_2.getCode() == req.getTemplateType()) {
            pageColumns = PageColumnConst.add(PageColumnConst.PowerVccUserTitles, PageColumnConst.PowerVccUserIndices);
        }

        String spId = ApplicationUtils.getWorkingSpId();

        //根据spId换path
        String path = departmentService.getPath(spId);

        //获取数据库连接
        InfluxDBConnect influxDBConnect = influxDBConfiguration.getInfluxDBConnect();
        List<Dtu> equipmentList = new ArrayList<>();
        LatestLogListRequest request = new LatestLogListRequest();
        if (!StringUtils.isEmpty(req.getImei()) || !StringUtils.isEmpty(req.getEquipmentName()) ||
                !StringUtils.isEmpty(req.getSubsCode()) || !StringUtils.isEmpty(req.getEquipmentType()) ||
                !StringUtils.isEmpty(req.getEquipmentManufacturer()) || !StringUtils.isEmpty(req.getEquipmentModel()) ||
                !StringUtils.isEmpty(req.getCustName()) || !StringUtils.isEmpty(req.getCustAddress()) ||
                !StringUtils.isEmpty(req.getCustPhone()) || !StringUtils.isEmpty(req.getIndustryType()) ||
                !StringUtils.isEmpty(req.getInstallationAddress()) || !StringUtils.isEmpty(req.getMemberId()) ||
                !StringUtils.isEmpty(req.getContactName()) || !StringUtils.isEmpty(req.getContactPhone()) || !StringUtils.isEmpty(req.getOrgCode()) ||
                !StringUtils.isEmpty(req.getCustomerAddress())) {

            BeanUtils.copyProperties(req, request);

            if (StringUtils.isEmpty(req.getEquipmentType())) {
                //查询全部
                request.setEquipmentTypes(new String[]{EquipmentType.INDEPENDENT_GAS_DETECTOR.getCode(),
                        EquipmentType.GAS_ALARM_CONTROLLER.getCode(), EquipmentType.HOME_GAS_DETECTOR.getCode()});
            } else {
                request.setEquipmentTypes(new String[]{req.getEquipmentType()});
            }
            request.setSpId(spId);
            if (TemplateTypeEnum.TEMPLATE_TYPE_1.getCode() == req.getTemplateType()) {
                equipmentList = equipmentService.listEquipmentWithType1(request);
            } else if (TemplateTypeEnum.TEMPLATE_TYPE_2.getCode() == req.getTemplateType()) {
                equipmentList = equipmentService.listEquipmentWithType2(request);
            }
            if (equipmentList.isEmpty()) {
                return new PageUtil(req.getPage(), req.getPageSize(), 0, resultList, pageColumns);
            }
            log.info(equipmentList.toString());
        }
        List<String> imeiList = equipmentList.stream().map(a -> {
            if (a.getEquipmentType().equals(EquipmentType.POINT_TYPE_GAS_DETECTOR.getCode())) {
                return org.apache.commons.lang.StringUtils.substringBefore(a.getIMEI(), "-");
            } else {
                return a.getIMEI();
            }
        }).collect(Collectors.toList());

        String where = "";
        String measurement = "select * from PowerLogAsDtu where Path='" + path + "'";
        String measurementCount = "select count(Ccid) from PowerLogAsDtu where Path='" + path + "'";
        if (!StringUtils.isEmpty(req.getTimeStart()) && !StringUtils.isEmpty(req.getTimeEnd())) {
            where = " and time>'" + req.getTimeStart() + "' and time<'" + req.getTimeEnd() + "'";
        }
        if (req.getOffline() != null) {
            where = where + " and Offline=" + req.getOffline();
        }
        if (imeiList != null && !imeiList.isEmpty()) {
            StringBuffer dtuWhere = new StringBuffer();
            dtuWhere.append(" and (DtuId='" + imeiList.get(0) + "'");
            for (int i = 1; i < imeiList.size(); i++) {
                dtuWhere.append(" or DtuId='" + imeiList.get(i) + "'");
            }
            dtuWhere.append(")");
            where = where + dtuWhere;
        }
        //数据权限
        List<String> permissionImeiIds = userPermissionService.getDepartDeviceIds(spId, ApplicationUtils.getUserId());
        if( null!=permissionImeiIds && !permissionImeiIds.isEmpty()){
            String imeiIdsStr = StringUtil.join(permissionImeiIds.toArray(new String[permissionImeiIds.size()]),"|");
            where = where + " and DtuId =~/^"+imeiIdsStr+"$/";
        }
        String sort = " order by time desc limit " + req.getPageSize() + " offset " + (req.getPage() - 1) * req.getPageSize();
        //查询influxDb的AlertLog的总数
        String countSql = measurementCount + where;
        log.info(countSql);
        QueryResult countResult = influxDBConnect.query(countSql);

        Integer count = 0;
        if (countResult.getResults().get(0).getSeries() != null) {
            Double c = (Double) countResult.getResults().get(0).getSeries().get(0).getValues().get(0).get(1);
            count = c.intValue();
        }
        //分页查询influxDb的AlertLog
        String selectSql = measurement + where + sort;
        log.info(selectSql);
        QueryResult queryResult = influxDBConnect.query(selectSql);
        List<List<Object>> list = new ArrayList<>();
        List<String> columns = new ArrayList<>();
        if (queryResult.getResults().get(0).getSeries() != null) {
            columns = queryResult.getResults().get(0).getSeries().get(0).getColumns();
            list = queryResult.getResults().get(0).getSeries().get(0).getValues();
        }
        log.info("list:{}", list.toString());
//        // 只查询被更改过的数据
//        QueryWrapper<DeviceState> deviceStateQueryWrapper = new QueryWrapper<>();
//        deviceStateQueryWrapper.lambda()
//                .eq(DeviceState::getIsDeleted, 0)
//                .eq(DeviceState::getDeviceStatusInfo, "设备离线（通讯不成功）")
//                .eq(DeviceState:: getSpId ,spId);
//        List<DeviceState> deviceStates = deviceStateMapper.selectList(deviceStateQueryWrapper);
//        // 创建一个map来存储
//        HashMap<String, DeviceState> deviceStateHashMap = new HashMap<>();
//        if (!CollectionUtils.isEmpty(deviceStates)){
//            for (DeviceState deviceState : deviceStates) {
//                deviceStateHashMap.put(deviceState.getDeviceId(),deviceState);
//            }
//        }
////        log.info("deviceStateHashMap:{}",deviceStateHashMap.toString());
        List<String> imeis = new ArrayList<>();
        for (List<Object> objects : list) {
            //log.info("objects1：{}", objects.get(9));
            PowerLogResponse res = new PowerLogResponse();
            res.setImei(objects.get(columns.indexOf("DtuId")).toString());
            res.setLatestTime(DateUtil.parse(objects.get(columns.indexOf("time")).toString()));
            res.setId(DateUtil.parse(objects.get(columns.indexOf("time")).toString()).getTime() * 1000000);
            res.setOffline(Boolean.valueOf(objects.get(columns.indexOf("Offline")).toString()));
            if (res.getOffline()) {
                res.setStartup("关机");
            } else {
                res.setStartup("开机");
            }
            if (objects.get(columns.indexOf("ConsumerId")) != null) {
                res.setConsumerId(Double.valueOf(objects.get(columns.indexOf("ConsumerId")).toString()).intValue());
            }

            if (Double.valueOf(objects.get(columns.indexOf("Version")).toString()).intValue() == 1000) {
                res.setDeviceCycle(true);
            }
            if (objects.get(columns.indexOf("Startup")) != null) {
                res.setStartup(objects.get(columns.indexOf("Startup")).toString());
            }
            // 根据imei去map中找，如果找到就设置为true，否则为false
//            log.info("deviceStateHashMap.get(res.getImei()):{}",deviceStateHashMap.get(res.getImei()).toString());
            log.info("objects：{}", objects.toString());
            imeis.add(res.getImei());
            resultList.add(res);
        }
        if (!imeis.isEmpty()) {
            LambdaQueryWrapper<Dtu> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.in(Dtu::getIMEI, imeis).eq(Dtu::getSpId, spId);
            List<Dtu> dtuList = equipmentService.list(queryWrapper);
            //设备厂商名称
            ConsoleSkSupplierListResponse response = equipmentCmpService.supplierListRequest();
            log.info("调用厨房查询厂商接口返回：{}", response);
            List<AlarmSupplierListVo> supplierListVos = new ArrayList<>();
            if (response != null && response.getCode() == 0 && response.getData() != null && org.apache.commons.collections.CollectionUtils.isNotEmpty(response.getData())) {
                supplierListVos = response.getData();
            }
            List<DictionaryItemRespDTO> equipmentTypeList = holder.getDictionaryByKey(EquipmentType.DICT_CODE);
            Map<String, Dtu> dtuMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(dtuList)){
                log.info(dtuList.toString());
                dtuMap = dtuList.stream().collect(Collectors.toMap(Dtu::getIMEI, Dtu -> Dtu, (a1, a2) -> a1));
            }
            for (PowerLogResponse powerLogResponse : resultList) {
                if (dtuMap.containsKey(powerLogResponse.getImei())) {
                    Dtu dtu = dtuMap.get(powerLogResponse.getImei());
                    BeanUtils.copyProperties(dtu, powerLogResponse);
                    DictionaryItemRespDTO dict = equipmentTypeList.stream().filter(a -> a.getValue().equals(
                            powerLogResponse.getEquipmentType())).collect(Collectors.toList()).get(0);
                    powerLogResponse.setEquipmentTypeName(dict.getName());
                    powerLogResponse.setEquipmentName(dtu.getName());
                    powerLogResponse.setConsumerId(dtu.getConsumerId());
                    List<AlarmSupplierListVo> listVos = supplierListVos.stream().filter(a -> a.getAlarmSystemCode().equals(
                            powerLogResponse.getEquipmentManufacturer())).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(listVos)) {
                        powerLogResponse.setManufactureName(listVos.get(0).getMsName());
                    }
                    if (TemplateTypeEnum.TEMPLATE_TYPE_2.getCode() == req.getTemplateType()) {
                        powerLogResponse.setInstallationAddress(dtu.getInstallationAddress());
                    }
                }

            }
            //客户信息
            List<Integer> consumerIds = resultList.stream().map(PowerLogResponse::getConsumerId).collect(Collectors.toList());
            LambdaQueryWrapper<Consumer> consumerQueryWrapper = new LambdaQueryWrapper<>();
            consumerQueryWrapper.eq(Consumer::getSpId, spId).in(Consumer::getId, consumerIds);
            List<Consumer> consumerList = consumerService.list(consumerQueryWrapper);
            Map<Integer, Consumer> consumerMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(consumerList)) {
                consumerMap = consumerList.stream().collect(Collectors.toMap(Consumer::getId, Consumer -> Consumer, (a1, a2) -> a1));
            }

            List<String> spIds = new ArrayList<>();
            spIds.add(spId);
            //查询组织架构名称
            List<CompanyResponse> companyNameList = companyService.queryCompanyNameList(spIds);
            Map<String, String> companyNameMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(companyNameList)) {
                companyNameMap = companyNameList.stream().collect(Collectors.toMap(CompanyResponse::getSpId, CompanyResponse::getName));
            }
            //批量查询字典
            List<DictionaryItemRespDTO> orgMapSubsCodeList = holder.getDictionaryByKey(ORG_MAP_SUBSCODE);
            Map<String, String> orgSubsCodeMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(orgMapSubsCodeList)) {
                orgSubsCodeMap = orgMapSubsCodeList.stream().collect(Collectors.toMap(DictionaryItemRespDTO::getDescription, DictionaryItemRespDTO::getCompanyName));
            }
            for (PowerLogResponse powerLogResponse : resultList) {
                if (consumerMap.containsKey(powerLogResponse.getConsumerId())) {
                    Consumer consumer = consumerMap.get(powerLogResponse.getConsumerId());
                    powerLogResponse.setCustomerAddress(consumer.getCustomerAddress());
                    //紫荆设备
                    if (powerLogResponse.getEquipmentFrom() == Constants.ZJ_EQUIPMENT_FROM) {
                        powerLogResponse.setMemberId(consumer.getMemberId());
                        powerLogResponse.setCustPhone(consumer.getCustPhone());
                    }
                    if (org.apache.commons.lang3.StringUtils.isNotEmpty(consumer.getOrgCode()) && orgSubsCodeMap.containsKey(consumer.getOrgCode())) {
                        powerLogResponse.setCompanyName(orgSubsCodeMap.get(consumer.getOrgCode()));
                    } else {
                        if (companyNameMap.containsKey(consumer.getSpId())) {
                            powerLogResponse.setCompanyName(companyNameMap.get(consumer.getSpId()));
                        }
                    }
                }
            }
            if (TemplateTypeEnum.TEMPLATE_TYPE_1.getCode() == req.getTemplateType()) {
                List<DictionaryItemRespDTO> industryTypeCodeList = holder.getDictionaryByKey(Constants.INDUSTRY_TYPE_CODE);
                //燃气用户
                for (PowerLogResponse powerLogResponse : resultList) {
                    if (consumerMap.containsKey(powerLogResponse.getConsumerId())) {
                        Consumer consumer = consumerMap.get(powerLogResponse.getConsumerId());
                        powerLogResponse.setSubsCode(consumer.getSubsCode());
                        powerLogResponse.setIndustryType(consumer.getIndustryType());
                        powerLogResponse.setCustName(consumer.getCustName());
                        powerLogResponse.setCustAddress(consumer.getCustAddress());
                        powerLogResponse.setCustPhone(consumer.getCustPhone());
                        powerLogResponse.setCustomerAddress(consumer.getCustomerAddress());
                        //设置行业类型名称
                        if (!StringUtils.isEmpty(powerLogResponse.getIndustryType())) {
                            DictionaryItemRespDTO communicationModeDict = industryTypeCodeList.stream().filter(a -> a.getValue().equals(
                                    powerLogResponse.getIndustryType())).collect(Collectors.toList()).get(0);
                            powerLogResponse.setIndustryTypeName(communicationModeDict.getName());
                        }
                    }
                }
            } else if (TemplateTypeEnum.TEMPLATE_TYPE_2.getCode() == req.getTemplateType()) {
                List<DictionaryItemRespDTO> industryTypeCodeList = holder.getDictionaryByKey(Constants.INDUSTRY_TYPE_CODE);
                //Vcc用户
                LambdaQueryWrapper<DtuBindingOrder> lqw = new LambdaQueryWrapper<>();
                lqw.eq(DtuBindingOrder::getSpId, spId).in(DtuBindingOrder::getConsumerId, consumerIds);
                List<DtuBindingOrder> bindings = dtuBindingOrderService.list(lqw);
                Map<String, DtuBindingOrder> bindingOrderMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(bindings)) {
                    bindingOrderMap = bindings.stream().collect(Collectors.toMap(DtuBindingOrder::getDeviceId, DtuBindingOrder -> DtuBindingOrder, (a1, a2) -> a1));
                }
                for (PowerLogResponse powerLogResponse : resultList) {
                    if (bindingOrderMap.containsKey(powerLogResponse.getImei())) {
                        DtuBindingOrder dtuBindingOrder = bindingOrderMap.get(powerLogResponse.getImei());
                        powerLogResponse.setMemberId(dtuBindingOrder.getMemberId());
                        powerLogResponse.setContactName(dtuBindingOrder.getCustName());
                        powerLogResponse.setContactPhone(dtuBindingOrder.getPhone());
                        if (StringUtils.isEmpty(dtuBindingOrder.getAddress())) {
                            powerLogResponse.setInstallationAddress(dtuBindingOrder.getRealAddress());
                        } else {
                            powerLogResponse.setInstallationAddress(dtuBindingOrder.getAddress());
                        }
                        Consumer consumerWithContacts = consumerList.stream().filter(item -> item.getId().equals(dtuBindingOrder.getConsumerId()))
                                .collect(Collectors.toList()).get(0);
                        powerLogResponse.setIndustryType(consumerWithContacts.getIndustryType());
                        //行业类型
                        if (!StringUtils.isEmpty(powerLogResponse.getIndustryType())) {
                            DictionaryItemRespDTO communicationModeDict = industryTypeCodeList.stream().filter(a -> a.getValue().equals(
                                    powerLogResponse.getIndustryType())).collect(Collectors.toList()).get(0);
                            powerLogResponse.setIndustryTypeName(communicationModeDict.getName());
                        }
                    }
                }
            }
        }
        PageUtil pageInfo = new PageUtil(req.getPage(), req.getPageSize(), count, resultList, pageColumns);
        return pageInfo;
    }
}
